#define _CRT_SECURE_NO_WARNINGS

#include "ChatClientPlugin.h"
#include "RakAssert.h"
#include "MessageIdentifiers.h"
#include "ChatOrder.h"
#include <stdlib.h>
#include <cstdio>
#include <cstring>

using namespace ChatApp;

ChatClientPlugin :: ChatClientPlugin()
{
	serverAddress = UNASSIGNED_SYSTEM_ADDRESS;
	friendRequest = -1;
	m_PackPos = 0;
} // End of ChatClientPlugin

ChatClientPlugin :: ~ChatClientPlugin()
{

} // End of ~ChatClientPlugin

void ChatClientPlugin::SetServerAddress( SystemAddress address )
{
	serverAddress = address;
} // End of SetServerAddress

void ChatClientPlugin::SetFriendId( int friendId )
{
	friendRequest = friendId;
} // End of SetFriendId

OrderMessage ChatClientPlugin::CreateOrder( char *message )
{
	RakAssert(message[0]);

	OrderMessage om;
	om.typeId = ID_CHAT_ORDER;

	if ( strcmp(message, "list") == 0 )
	{
		om.order = CO_CLIENT_LIST;
		strcpy(om.message, "\0");
		om.memberId = -1;
		return om;
	}

	if ( strcmp(message, "friendlist") == 0 )
	{
		om.order = CO_FRIEND_LIST;
		strcpy(om.message, "\0");
		om.memberId = -1;

		return om;
	} // End if

	if ( IsOrder(message, "friend ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 7 + MAX_DIGIT_BIT && 
			 IsNumber(message, 7, 7 + MAX_DIGIT_BIT) )
		{
			om.order = CO_FRIEND_REQUEST;
			om.memberId = atoi(SubString(message, 7, 7 + MAX_DIGIT_BIT));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if

	if ( IsOrder(message, "to ", 0) )
	{
		if ( IsNumber(message, 3, 3 + MAX_DIGIT_BIT) && 
			 message[3 + MAX_DIGIT_BIT] == ' ')
		{
			om.order = CO_PRIVATE_CHAT;
			strcpy(om.message, 
				   SubString(message, 4 + MAX_DIGIT_BIT, strlen(message)));
			om.memberId = atoi(SubString(message, 3, 3 + MAX_DIGIT_BIT));
		} // End if
		else
		{
			strcpy(om.message, "\0");
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if

    if ( IsOrder(message, "name ", 0) )
    {
        om.order = CO_CHATTER_NAME;
        strcpy(om.message, 
            SubString(message, 5, strlen(message)));
        om.memberId = -1;
        return om;
    } // End if

    if ( IsOrder(message, "roll ", 0) )
    {
        strcpy(om.message, "\0");
        if ( strlen(message) <= 5 + MAX_ROLL_NUM && 
            IsNumber(message, 5, strlen(message)) )
        {
            om.order = CO_CHATTER_ROLL;
            om.memberId = atoi(SubString(message, 5, strlen(message)));

            if(om.memberId == 0)
            {
                om.order = CO_NOT_ORDER;
                printf("Request Failed: Order Format Error!\n");
            } // End if
        } // End if
        else
        {
            om.order = CO_NOT_ORDER;
            printf("Request Failed: Order Format Error!\n");
        } // End else

        return om;
    } // End if

	if ( strcmp(message, "packall") == 0 )
	{
		om.order = CO_GAME_PACKALL;
		strcpy(om.message, "\0");
		om.memberId = -1;

		return om;
	} // End if


    if ( strcmp(message, "pack") == 0 )
    {
        om.order = CO_GAME_PACK;
        strcpy(om.message, "\0");
        om.memberId = -1;

        return om;
    } // End if


    if ( IsOrder(message, "lv ", 0) )
    {
        strcpy(om.message, "\0");
        if ( strlen(message) <= 3 + MAX_ROLL_NUM && 
            IsNumber(message, 3, strlen(message)) )
        {
            om.order = CO_GAME_LV;
            om.memberId = atoi(SubString(message, 3, strlen(message)));
        } // End if
        else
        {
            om.order = CO_NOT_ORDER;
            printf("Request Failed: Order Format Error!\n");
        } // End else

        return om;
    } // End if

	if ( IsOrder(message, "lv-r ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 5 + MAX_ROLL_NUM && 
			IsNumber(message, 5, strlen(message)) )
		{
			om.order = CO_GAME_LV;
			om.memberId = 0 - atoi(SubString(message, 5, strlen(message)));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if
    
	if ( IsOrder(message, "exp ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 4 + MAX_ROLL_NUM && 
			IsNumber(message, 4, strlen(message)) )
		{
			om.order = CO_GAME_EXP;
			om.memberId = atoi(SubString(message, 4, strlen(message)));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if

	if ( IsOrder(message, "exp-r ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 6 + MAX_ROLL_NUM && 
			IsNumber(message, 6, strlen(message)) )
		{
			om.order = CO_GAME_EXP;
			om.memberId = 0 - atoi(SubString(message, 6, strlen(message)));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if

    if ( IsOrder(message, "hp ", 0) )
    {
        strcpy(om.message, "\0");
        if ( strlen(message) <= 3 + MAX_ROLL_NUM && 
            IsNumber(message, 3, strlen(message)) )
        {
            om.order = CO_GAME_HP;
            om.memberId = atoi(SubString(message, 3, strlen(message)));
        } // End if
        else
        {
            om.order = CO_NOT_ORDER;
            printf("Request Failed: Order Format Error!\n");
        } // End else

        return om;
    } // End if

	if ( IsOrder(message, "hp-r ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 5 + MAX_ROLL_NUM && 
			IsNumber(message, 5, strlen(message)) )
		{
			om.order = CO_GAME_HP;
			om.memberId = 0 - atoi(SubString(message, 5, strlen(message)));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if

    if ( IsOrder(message, "mp ", 0) )
    {
        strcpy(om.message, "\0");
        if ( strlen(message) <= 3 + MAX_ROLL_NUM && 
            IsNumber(message, 3, strlen(message)) )
        {
            om.order = CO_GAME_MP;
            om.memberId = atoi(SubString(message, 3, strlen(message)));
        } // End if
        else
        {
            om.order = CO_NOT_ORDER;
            printf("Request Failed: Order Format Error!\n");
        } // End else

        return om;
    } // End if

    if ( IsOrder(message, "mp-r ", 0) )
    {
        strcpy(om.message, "\0");
        if ( strlen(message) <= 5 + MAX_ROLL_NUM && 
            IsNumber(message, 5, strlen(message)) )
        {
            om.order = CO_GAME_MP;
            om.memberId = 0 - atoi(SubString(message, 5, strlen(message)));
        } // End if
        else
        {
            om.order = CO_NOT_ORDER;
            printf("Request Failed: Order Format Error!\n");
        } // End else

        return om;
    } // End if

    if ( IsOrder(message, "str ", 0) )
    {
        strcpy(om.message, "\0");
        if ( strlen(message) <= 4 + MAX_ROLL_NUM && 
            IsNumber(message, 4, strlen(message)) )
        {
            om.order = CO_GAME_STR;
            om.memberId = atoi(SubString(message, 4, strlen(message)));
        } // End if
        else
        {
            om.order = CO_NOT_ORDER;
            printf("Request Failed: Order Format Error!\n");
        } // End else

        return om;
    } // End if

	if ( IsOrder(message, "str-r ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 6 + MAX_ROLL_NUM && 
			IsNumber(message, 6, strlen(message)) )
		{
			om.order = CO_GAME_STR;
			om.memberId = 0 - atoi(SubString(message, 6, strlen(message)));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if


    if ( IsOrder(message, "def ", 0) )
    {
        strcpy(om.message, "\0");
        if ( strlen(message) <= 4 + MAX_ROLL_NUM && 
            IsNumber(message, 4, strlen(message)) )
        {
            om.order = CO_GAME_DEF;
            om.memberId = atoi(SubString(message, 4, strlen(message)));
        } // End if
        else
        {
            om.order = CO_NOT_ORDER;
            printf("Request Failed: Order Format Error!\n");
        } // End else

        return om;
    } // End if

	if ( IsOrder(message, "def-r ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 6 + MAX_ROLL_NUM && 
			IsNumber(message, 6, strlen(message)) )
		{
			om.order = CO_GAME_DEF;
			om.memberId = 0 - atoi(SubString(message, 6, strlen(message)));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if

    if ( IsOrder(message, "hit ", 0) )
    {
        strcpy(om.message, "\0");
        if ( strlen(message) <= 4 + MAX_ROLL_NUM && 
            IsNumber(message, 4, strlen(message)) )
        {
            om.order = CO_GAME_HIT;
            om.memberId = atoi(SubString(message, 4, strlen(message)));
        } // End if
        else
        {
            om.order = CO_NOT_ORDER;
            printf("Request Failed: Order Format Error!\n");
        } // End else

        return om;
    } // End if

	if ( IsOrder(message, "hit-r ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 6 + MAX_ROLL_NUM && 
			IsNumber(message, 6, strlen(message)) )
		{
			om.order = CO_GAME_HIT;
			om.memberId = atoi(SubString(message, 6, strlen(message)));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if


    if ( IsOrder(message, "dex ", 0) )
    {
        strcpy(om.message, "\0");
        if ( strlen(message) <= 4 + MAX_ROLL_NUM && 
            IsNumber(message, 4, strlen(message)) )
        {
            om.order = CO_GAME_DEX;
            om.memberId = atoi(SubString(message, 4, strlen(message)));
        } // End if
        else
        {
            om.order = CO_NOT_ORDER;
            printf("Request Failed: Order Format Error!\n");
        } // End else

        return om;
    } // End if

	if ( IsOrder(message, "dex-r ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 6 + MAX_ROLL_NUM && 
			IsNumber(message, 6, strlen(message)) )
		{
			om.order = CO_GAME_DEX;
			om.memberId = 0 - atoi(SubString(message, 6, strlen(message)));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if


    if ( IsOrder(message, "int ", 0) )
    {
        strcpy(om.message, "\0");
        if ( strlen(message) <= 4 + MAX_ROLL_NUM && 
            IsNumber(message, 4, strlen(message)) )
        {
            om.order = CO_GAME_INT;
            om.memberId = atoi(SubString(message, 4, strlen(message)));
        } // End if
        else
        {
            om.order = CO_NOT_ORDER;
            printf("Request Failed: Order Format Error!\n");
        } // End else

        return om;
    } // End if

	if ( IsOrder(message, "int-r ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 6 + MAX_ROLL_NUM && 
			IsNumber(message, 6, strlen(message)) )
		{
			om.order = CO_GAME_INT;
			om.memberId = 0 - atoi(SubString(message, 6, strlen(message)));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if


    if ( IsOrder(message, "mdf ", 0) )
    {
        strcpy(om.message, "\0");
        if ( strlen(message) <= 4 + MAX_ROLL_NUM && 
            IsNumber(message, 4, strlen(message)) )
        {
            om.order = CO_GAME_MDF;
            om.memberId = atoi(SubString(message, 4, strlen(message)));
        } // End if
        else
        {
            om.order = CO_NOT_ORDER;
            printf("Request Failed: Order Format Error!\n");
        } // End else

        return om;
    } // End if

	if ( IsOrder(message, "mdf-r ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 6 + MAX_ROLL_NUM && 
			IsNumber(message, 6, strlen(message)) )
		{
			om.order = CO_GAME_MDF;
			om.memberId = 0 - atoi(SubString(message, 6, strlen(message)));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if

    if ( IsOrder(message, "gold ", 0) )
    {
        strcpy(om.message, "\0");
        if ( strlen(message) <= 5 + MAX_ROLL_NUM && 
            IsNumber(message, 5, strlen(message)) )
        {
            om.order = CO_GAME_GOLD;
            om.memberId = atoi(SubString(message, 5, strlen(message)));
        } // End if
        else
        {
            om.order = CO_NOT_ORDER;
            printf("Request Failed: Order Format Error!\n");
        } // End else

        return om;
    } // End if

	if ( IsOrder(message, "gold-r ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 7 + MAX_ROLL_NUM && 
			IsNumber(message, 7, strlen(message)) )
		{
			om.order = CO_GAME_GOLD;
			om.memberId = 0 - atoi(SubString(message, 7, strlen(message)));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if

    if ( IsOrder(message, "carry ", 0) )
    {
        strcpy(om.message, "\0");
        if ( strlen(message) <= 6 + MAX_ROLL_NUM && 
            IsNumber(message, 6, strlen(message)) )
        {
            om.order = CO_GAME_CARRY;
            om.memberId = atoi(SubString(message, 6, strlen(message)));
        } // End if
        else
        {
            om.order = CO_NOT_ORDER;
            printf("Request Failed: Order Format Error!\n");
        } // End else

        return om;
    } // End if

	if ( IsOrder(message, "carry-r ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 8 + MAX_ROLL_NUM && 
			IsNumber(message, 8, strlen(message)) )
		{
			om.order = CO_GAME_CARRY;
			om.memberId = 0 - atoi(SubString(message, 8, strlen(message)));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if

    if ( IsOrder(message, "maxcarry ", 0) )
    {
        strcpy(om.message, "\0");
        if ( strlen(message) <= 9 + MAX_ROLL_NUM && 
            IsNumber(message, 9, strlen(message)) )
        {
            om.order = CO_GAME_MAXCARRY;
            om.memberId = atoi(SubString(message, 9, strlen(message)));
        } // End if
        else
        {
            om.order = CO_NOT_ORDER;
            printf("Request Failed: Order Format Error!\n");
        } // End else

        return om;
    } // End if

	if ( IsOrder(message, "maxcarry-r ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 11 + MAX_ROLL_NUM && 
			IsNumber(message, 11, strlen(message)) )
		{
			om.order = CO_GAME_MAXCARRY;
			om.memberId = 0 - atoi(SubString(message, 11, strlen(message)));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if

	if ( IsOrder(message, "equip ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 6 + MAX_ROLL_NUM && 
			IsNumber(message, 6, strlen(message)) )
		{
			om.order = CO_GAME_EQUIP;
			om.memberId = atoi(SubString(message, 6, strlen(message)));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if

	if ( IsOrder(message, "unequip ", 0) )
	{
		strcpy(om.message, "\0");
		if ( strlen(message) <= 8 + MAX_ROLL_NUM && 
			IsNumber(message, 8, strlen(message)) )
		{
			om.order = CO_GAME_UNEQUIP;
			om.memberId = atoi(SubString(message, 8, strlen(message)));
		} // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
	} // End if

    if ( IsOrder(message, "insert ", 0) )
    {
		++m_PackPos;
        om.order = CO_PACK_INSERT;
        strcpy(om.message, 
            SubString(message, 7, strlen(message)));
        om.memberId = m_PackPos;
        return om;
    } // End if

    if ( IsOrder(message, "drop ", 0) )
    {
        strcpy(om.message, "\0");
        if ( strlen(message) <= 5 + MAX_ROLL_NUM && 
            IsNumber(message, 5, strlen(message)) )
        {
            om.order = CO_PACK_DROP;
            om.memberId = atoi(SubString(message, 5, strlen(message)));
        } // End if
		else
		{
			om.order = CO_NOT_ORDER;
			printf("Request Failed: Order Format Error!\n");
		} // End else

		return om;
    } // End if

	if ( friendRequest >= 0 )
	{
		if ( strcmp(message, "Y") == 0 || strcmp(message, "y") == 0 )
		{
			strcpy(om.message, "\0");
			om.order = CO_FRIEND_REQUEST_AGREE;
			om.memberId = friendRequest;
			friendRequest = -1;
		} // End if
        if ( strcmp(message, "N") == 0 || strcmp(message, "n") == 0 )
		{
			strcpy(om.message, "\0");
			om.order = CO_FRIEND_REQUEST_REFUSE;
			om.memberId = friendRequest;
			friendRequest = -1;
		} // End if
		
		return om;
	} // End if


    om.order = CO_NOT_ORDER;
	strcpy(om.message, message);

	return om;
} // End of CreateOrder

PluginReceiveResult ChatClientPlugin::OnReceive( RakPeerInterface *peer, 
												 Packet *packet )
{
	RakAssert(packet);
	RakAssert(peer);

	// printf("check\n");
	unsigned char packetIdentifier;
	packetIdentifier = GetPacketId(packet);

	switch ( packetIdentifier )
	{
	case ID_CONNECTION_LOST :
		{

		} // End case
		break;

	case ID_DISCONNECTION_NOTIFICATION :
		{
			OnCloseConnection(peer, packet->systemAddress);
		} // End case
		break;

	case ID_CHAT_ORDER :
		{
			OrderMessage *tempOm = (ChatApp::OrderMessage *) packet->data;
			RakAssert(packet->length == sizeof(OrderMessage));

			switch ( tempOm->order )
			{
			case CO_FRIEND_REQUEST :
				{
					if ( friendRequest >= 0 )
					{			
						OrderMessage om;
						om.typeId = ID_CHAT_ORDER;
						om.order = ChatApp::CO_CHATTER_BUSY;
						strcpy(om.message, "\0");
						om.memberId = tempOm->memberId;

						peer->Send((const char*)&om,
							       (const int)sizeof(om),
								   HIGH_PRIORITY,
								   RELIABLE_ORDERED,
								   0,
								   UNASSIGNED_SYSTEM_ADDRESS,
								   true);
					} // End if
					else
					{
						printf("%s\n",tempOm->message);
						SetFriendId(tempOm->memberId);
					} // End else
					return RR_STOP_PROCESSING_AND_DEALLOCATE;
				}// End case
				break;

			} // End switch


		} // End case
		break;
	} // End switch

	return RR_CONTINUE_PROCESSING;
} // End of OnRecevie

void ChatClientPlugin::OnCloseConnection( RakPeerInterface *peer, 
										  SystemAddress systemAddress )
{
    peer->CloseConnection(serverAddress, true);
} // End of OnCloseConnection

void ChatClientPlugin::OnShutdown( RakPeerInterface *peer )
{
    peer->CloseConnection(serverAddress, true);
} // End of OnShutdown

bool ChatClientPlugin::IsOrder( char *message, char *order, int pos )
{
	if ( ( pos > strlen(message) - strlen(order) - 1 ) || pos < 0)
	{
		return false;
	} // End if

	for ( int i = 0; i < strlen(order); ++i )
	{
		if ( message[pos + i] != order[i] )
		{
			return false;
		} // End if
	} // End for

	return true;
} // End of IsOrder

bool ChatClientPlugin::IsNumber( char *message, int beginp, int endp )
{
	if ( //endp > strlen(message) || 
		 beginp >= endp || 
		 beginp < 0 || 
		 endp < 0 )
	{
		return false;
	} // End if

	// Check if every character is a number
	for ( int i = beginp; i < endp; ++i )
	{
		if ( message[i] > '9' || (message[i] < '0' && message[i] != 0))
		{
			return false;
		} // End if
	} // End for

	return true;
} // End of IsNumber

char* ChatClientPlugin::SubString( char *message, int beginp, int endp )
{
	char* temp = (char *)malloc(endp - beginp + 1);

	if ( endp > strlen(message) || 
		 beginp >= endp || 
		 beginp < 0 || 
		 endp < 0 )
	{
		temp[0] = '\0';
		return temp;
	} // End if

	for ( int i = 0; i < endp - beginp; ++i )
	{
		temp[i] = message[beginp + i];
	} // End for
	temp[endp - beginp] = '\0';

	return temp;
} // End of SubString

unsigned char ChatClientPlugin :: GetPacketId( Packet *p )
{
	if ( p == 0 )
	{
		return 255;
	} // End if

	if ( (unsigned char)p->data[0] == ID_TIMESTAMP )
	{
		RakAssert(p->length > sizeof(unsigned char) + sizeof(unsigned long));
		return (unsigned char) p->data[sizeof(unsigned char) + sizeof(unsigned long)];
	} // End if
	else
	{
		return (unsigned char) p->data[0];
	} // End else
} // End of GetPacketIdentifier

void ChatClientPlugin :: OnSend( RakPeerInterface *peer, char *message)
{
	OrderMessage om = CreateOrder( message );

	if ( om.order == ChatApp::CO_NOT_ORDER )
	{
		if ( om.message[0] != 0 )
		{
			// message is the data to send
			// strlen(message)+1 is to send the null terminator
			// HIGH_PRIORITY doesn't actually matter here because we don't use any other priority
			// RELIABLE_ORDERED means make sure the message arrives in the right order
			bool temp = peer->Send(om.message,
				(int) strlen(om.message) + 1,
				HIGH_PRIORITY,
				RELIABLE_ORDERED,
				0,
				UNASSIGNED_SYSTEM_ADDRESS,
				true);
		} // End if
	} // End if
	else
	{
		peer->Send((const char*)&om,
			(const int)sizeof(om),
			HIGH_PRIORITY,
			RELIABLE_ORDERED,
			0,
			UNASSIGNED_SYSTEM_ADDRESS,
			true);
	} // End else
} // End of OnSend